import datetime
import time

from bson import ObjectId
from fastapi import APIRouter
from mongoengine import Q

from app.core.globol import Globol
from app.core.return_info import ReturnInfo, SUCCESS, FAILED
from app.sql_app.mongodbmodels import JssWFPanterntPageModel, JssWFPanterntPage, JssWFPanterntDetailModel, \
    JssWFPanterntDetail, WFJournalPageModel, WFJournalPage, CnkiJournalIdPageModel, CnkiJournalIdPage, CnkiIssueModel, \
    CnkiIssue, CnkiJournalModel, CnkiJournal, CnkiArticleIdModel, CnkiArticleId, CnkiArticleDetailModel, \
    CnkiArticleDetail, PdfIpModel, PdfIp, UpdatePdfIpModel, CnkiBsRefModel, CnkiBsRef, CnkiArticleDetailRedownModel, \
    CnkiArticleDetailRedown

router = APIRouter()


@router.post("/insert/jsswfpantentpage")
async def create_note(page: JssWFPanterntPageModel):
    return_info = ReturnInfo()
    jwpp = JssWFPanterntPage.objects(cid=page.cid, pagenum=page.pagenum)
    if jwpp:  # mongoengine.queryset.queryset.QuerySet
        jwpp.update(down_date=page.down_date, html=page.html, update_time=datetime.datetime.now())
        # jwpp.reload()
        return_info.status = SUCCESS
        return_info.data = {"boos": [str(j.id) for j in jwpp]}
        return return_info.todict()  #
    else:
        jwpp = JssWFPanterntPage(cid=page.cid, pagenum=page.pagenum,
                                 down_date=page.down_date, html=page.html,
                                 update_time=datetime.datetime.now(),
                                 create_time=datetime.datetime.now()
                                 )
        jwpp.save()
        return_info.status = SUCCESS
        return_info.data = {"boos": str(jwpp.id)}
        return return_info.todict()


@router.get("/get/jsswfpantentpageid")
def read_root(_id: str = None):
    id_list = list()
    if _id is None:
        m_result = JssWFPanterntPage.objects().fields(id=1).limit(1)
    else:
        m_result = JssWFPanterntPage.objects(id__gt=_id).fields(id=1).limit(10000)
    for r in m_result:
        id_list.append(str(r.id))
    return id_list


@router.get("/get/jsswfpantentpagehtml")
def read_root(_id: str):
    info_dict = dict()
    m_result = JssWFPanterntPage.objects(id=_id)
    for info in m_result:
        info_dict['cid'] = info['cid']
        info_dict['pagenum'] = info['pagenum']
        info_dict['html'] = info['html']
    return info_dict


@router.post("/insert/jsswfpantentdetail")
async def create_note(detail: JssWFPanterntDetailModel):
    return_info = ReturnInfo()
    jwpp = JssWFPanterntDetail.objects(rawid=detail.rawid)
    if jwpp:  # mongoengine.queryset.queryset.QuerySet
        jwpp.update(
            cid=detail.cid, pagenum=detail.pagenum, detail_url=detail.detail_url,
            down_date=detail.down_date, html=detail.html,
            update_time=datetime.datetime.now())
        # jwpp.reload()
        return_info.status = SUCCESS
        return_info.data = {"boos": [str(j.id) for j in jwpp]}
        return return_info.todict()
    else:
        jwpp = JssWFPanterntDetail(rawid=detail.rawid, cid=detail.cid,
                                   pagenum=detail.pagenum, detail_url=detail.detail_url,
                                   down_date=detail.down_date, html=detail.html,export_stat=detail.export_stat,
                                   update_time=datetime.datetime.now(),
                                   create_time=datetime.datetime.now()
                                   )
        jwpp.save()
        return_info.status = SUCCESS
        return_info.data = {"boos": str(jwpp.id)}
        return return_info.todict()


@router.post("/insert/wfjournalpage")
async def create_note(page: WFJournalPageModel):
    return_info = ReturnInfo()
    jwpp = WFJournalPage.objects(cid=page.cid, pagenum=page.pagenum)
    if jwpp:  # mongoengine.queryset.queryset.QuerySet
        jwpp.update(
            cid=page.cid, pagenum=page.pagenum, jsondicts=page.jsondicts,
            update_time=datetime.datetime.now())
        # jwpp.reload()
        return_info.status = SUCCESS
        return_info.data = {"boos": [str(j.id) for j in jwpp]}
        return return_info.todict()
    else:
        jwpp = WFJournalPage(cid=page.cid, pagenum=page.pagenum,
                             jsondicts=page.jsondicts,
                             update_time=datetime.datetime.now(),
                             create_time=datetime.datetime.now()
                             )
        jwpp.save()
        return_info.status = SUCCESS
        return_info.data = {"boos": str(jwpp.id)}
        return return_info.todict()


@router.post("/insert/cnkijournalidpage")
async def create_note(page: CnkiJournalIdPageModel):
    return_info = ReturnInfo()
    cjip = CnkiJournalIdPage.objects(pagenum=page.pagenum)
    if cjip:  # mongoengine.queryset.queryset.QuerySet
        cjip.update(
            pagenum=page.pagenum, html=page.html,
            update_time=datetime.datetime.now())
        # jwpp.reload()
        return_info.status = SUCCESS
        return_info.data = {"boos": [str(j.id) for j in cjip]}
        return return_info.todict()
    else:
        cjip = CnkiJournalIdPage(pagenum=page.pagenum, html=page.html,
                                 update_time=datetime.datetime.now(),
                                 create_time=datetime.datetime.now()
                                 )
        cjip.save()
        return_info.status = SUCCESS
        return_info.data = {"boos": str(cjip.id)}
        return return_info.todict()


@router.post("/insert/cnkijournalissue")
async def create_note(issue: CnkiIssueModel):
    return_info = ReturnInfo()
    cjip = CnkiIssue.objects(pykm=issue.pykm)
    if cjip:  # mongoengine.queryset.queryset.QuerySet
        cjip.update(
            pykm=issue.pykm, html=issue.html,
            update_time=datetime.datetime.now())
        # jwpp.reload()
        return_info.status = SUCCESS
        return_info.data = {"boos": [str(j.id) for j in cjip]}
        return return_info.todict()
    else:
        cjip = CnkiIssue(pykm=issue.pykm, html=issue.html,
                         update_time=datetime.datetime.now(),
                         create_time=datetime.datetime.now()
                         )
        cjip.save()
        return_info.status = SUCCESS
        return_info.data = {"boos": str(cjip.id)}
        return return_info.todict()


@router.post("/insert/cnkijournaldetail")
async def create_note(journal: CnkiJournalModel):
    return_info = ReturnInfo()
    cjip = CnkiJournal.objects(pykm=journal.pykm)
    if cjip:  # mongoengine.queryset.queryset.QuerySet
        cjip.update(
            pykm=journal.pykm, html=journal.html,
            update_time=datetime.datetime.now())
        # jwpp.reload()
        return_info.status = SUCCESS
        return_info.data = {"boos": [str(j.id) for j in cjip]}
        return return_info.todict()
    else:
        cjip = CnkiJournal(pykm=journal.pykm, html=journal.html,
                           update_time=datetime.datetime.now(),
                           create_time=datetime.datetime.now()
                           )
        cjip.save()
        return_info.status = SUCCESS
        return_info.data = {"boos": str(cjip.id)}
        return return_info.todict()


@router.post("/insert/cnkiarticleid")
async def create_note(articleid: CnkiArticleIdModel):
    return_info = ReturnInfo()
    cjip = CnkiArticleId.objects(ids=articleid.ids)
    if cjip:  # mongoengine.queryset.queryset.QuerySet
        cjip.update(
            pykm=articleid.pykm, years=articleid.years,
            nums=articleid.nums, articlecount=articleid.articlecount,
            html=articleid.html, update_time=datetime.datetime.now())
        # jwpp.reload()
        return_info.status = SUCCESS
        return_info.data = {"boos": [str(j.id) for j in cjip]}
        return return_info.todict()
    else:
        cjip = CnkiArticleId(ids=articleid.ids, pykm=articleid.pykm,
                             years=articleid.years, nums=articleid.nums,
                             articlecount=articleid.articlecount,
                             html=articleid.html,
                             update_time=datetime.datetime.now(),
                             create_time=datetime.datetime.now()
                             )
        cjip.save()
        return_info.status = SUCCESS
        return_info.data = {"boos": str(cjip.id)}
        return return_info.todict()


@router.post("/insert/cnkiarticledetail")
async def create_note(articledetail: CnkiArticleDetailModel):
    return_info = ReturnInfo()
    cjip = CnkiArticleDetail.objects(articleid=articledetail.articleid)
    if cjip:  # mongoengine.queryset.queryset.QuerySet
        if articledetail.htmldicts and articledetail.refdicts:
            cjip.update(
                htmldicts=articledetail.htmldicts, refdicts=articledetail.refdicts,
                update_time=datetime.datetime.now())
        elif articledetail.htmldicts:
            cjip.update(
                htmldicts=articledetail.htmldicts, update_time=datetime.datetime.now())
        elif articledetail.refdicts:
            cjip.update(
                refdicts=articledetail.refdicts, update_time=datetime.datetime.now())
        # jwpp.reload()
        return_info.status = SUCCESS
        return_info.data = {"boos": [str(j.id) for j in cjip]}
        print(return_info.data)
        return return_info.todict()
    else:
        cjip = CnkiArticleDetail(articleid=articledetail.articleid,
                                 htmldicts=articledetail.htmldicts,
                                 refdicts=articledetail.refdicts,
                                 update_time=datetime.datetime.now(),
                                 create_time=datetime.datetime.now())
        cjip.save()
        return_info.status = SUCCESS
        return_info.data = {"boos": str(cjip.id)}
        return return_info.todict()


@router.post("/insert/cnkiarticledetailredown")
async def create_note(articledetail: CnkiArticleDetailRedownModel):
    return_info = ReturnInfo()
    cjip = CnkiArticleDetailRedown.objects(articleid=articledetail.articleid)
    if cjip:  # mongoengine.queryset.queryset.QuerySet
        if articledetail.htmldicts and articledetail.refdicts:
            cjip.update(
                htmldicts=articledetail.htmldicts, refdicts=articledetail.refdicts,
                update_time=datetime.datetime.now())
        elif articledetail.htmldicts:
            cjip.update(
                htmldicts=articledetail.htmldicts, update_time=datetime.datetime.now())
        elif articledetail.refdicts:
            cjip.update(
                refdicts=articledetail.refdicts, update_time=datetime.datetime.now())
        # jwpp.reload()
        return_info.status = SUCCESS
        return_info.data = {"boos": [str(j.id) for j in cjip]}
        print(return_info.data)
        return return_info.todict()
    else:
        cjip = CnkiArticleDetailRedown(articleid=articledetail.articleid,
                                       htmldicts=articledetail.htmldicts,
                                       refdicts=articledetail.refdicts,
                                       update_time=datetime.datetime.now(),
                                       create_time=datetime.datetime.now())
        cjip.save()
        return_info.status = SUCCESS
        return_info.data = {"boos": str(cjip.id)}
        return return_info.todict()


@router.post("/insert/addcnkiarticledetailref")
async def create_note(articleid: str, dictkey: str, dicts: dict):
    return_info = ReturnInfo()
    cjip = CnkiArticleDetail.objects(articleid=articleid)
    if cjip:  # mongoengine.queryset.queryset.QuerySet
        cjip_one = cjip.first()
        refdicts = cjip_one.refdicts
        refdicts[dictkey] = dicts
        stat = 1
        for k, v in refdicts.items():
            if v == {}:
                stat = 0
        refdicts["stat"] = stat
        cjip_one.update(refdicts=refdicts, update_time=datetime.datetime.now())
        # jwpp.reload()
        return_info.status = SUCCESS
        return_info.data = {"boos": [str(j.id) for j in cjip]}
        return return_info.todict()
    else:
        return_info.status = FAILED
        return_info.msg = "{}不存在".format(articleid)
        return_info.data = {"boos": str(cjip.id)}
        return return_info.todict()

@router.post("/insert/addcnkiarticledetailrefredown")
async def create_note(articleid: str, dictkey: str, dicts: dict):
    return_info = ReturnInfo()
    cjip = CnkiArticleDetailRedown.objects(articleid=articleid)
    if cjip:  # mongoengine.queryset.queryset.QuerySet
        cjip_one = cjip.first()
        refdicts = cjip_one.refdicts
        refdicts[dictkey] = dicts
        stat = 1
        for k, v in refdicts.items():
            if v == {}:
                stat = 0
        refdicts["stat"] = stat
        cjip_one.update(refdicts=refdicts, update_time=datetime.datetime.now())
        # jwpp.reload()
        return_info.status = SUCCESS
        return_info.data = {"boos": [str(j.id) for j in cjip]}
        return return_info.todict()
    else:
        return_info.status = FAILED
        return_info.msg = "{}不存在".format(articleid)
        return_info.data = {"boos": str(cjip.id)}
        return return_info.todict()


@router.get("/search/cnkiarticledetail/{articleid}")
async def create_note(articleid: str):
    return_info = ReturnInfo()
    cjip = CnkiArticleDetail.objects(articleid=articleid)
    if cjip:
        return_info.status = SUCCESS
    else:
        return_info.status = FAILED
    return return_info.todict()


@router.get("/search/cnkiarticledetailref")
async def create_note():
    """
    还没有开始下载引文的数据
    :return:
    """
    return_info = ReturnInfo()
    # 这种方法效率慢
    # cjip = CnkiArticleDetail.objects(htmldicts__refcount__REFERENCE__gt="0", refdicts={})[:1000]
    # cjip = CnkiArticleDetail.objects(Q(htmldicts__refcount__REFERENCE__gt="0") & Q(refdicts__stat__exists=False))[:1000]
    cjip = CnkiArticleDetail.objects(refdicts__stat=0).fields(articleid=1, htmldicts__refcount__REFERENCE=1).limit(1000)
    if cjip:
        return_info.status = SUCCESS
        return_info.data = {"boos": [(str(j.id), str(j.htmldicts["refcount"]["REFERENCE"])) for j in cjip]}
    else:
        return_info.status = FAILED
        return_info.msg = "数据不存在"
    return return_info.todict()


@router.get("/search/cnkiarticledetailref2")
async def create_note():
    """
    开始下载 但完整性验证没通过的数据
    :return:
    """
    return_info = ReturnInfo()
    # cjip = CnkiArticleDetail.objects(htmldicts__refcount__REFERENCE__gt="0", refdicts__stat=0).fields(refdicts=1).limit(
    #     10000)
    cjip = CnkiArticleDetail.objects(refdicts__stat=0).fields(refdicts=1, htmldicts__refcount__REFERENCE=1).limit(
        1000)
    if cjip:
        return_info.status = SUCCESS
        dicts = {}
        for j in cjip:
            if j.htmldicts["refcount"]["REFERENCE"] == "0":
                print("htmldicts__refcount__REFERENCE = 0;" + str(j.id))
                one_detail = CnkiArticleDetail.objects(articleid=str(j.id))
                one_detail.update(refdicts__stat=1, update_time=datetime.datetime.now())
                continue
            lists = []
            have_v = False
            for k, v in j.refdicts.items():
                if k == "stat":
                    continue
                if v == {}:
                    lists.append(k)
                else:
                    have_v = True

            if have_v and len(lists) == 0:
                print("refdicts__stat = 1;" + str(j.id))
                one_detail = CnkiArticleDetail.objects(articleid=str(j.id))
                one_detail.update(refdicts__stat=1, update_time=datetime.datetime.now())
                continue
            dicts[str(j.id)] = lists

        return_info.data = {"boos": dicts}
    else:
        return_info.status = FAILED
        return_info.msg = "数据不存在"
    return return_info.todict()


@router.post("/insert/cnkiarticleid")
async def create_note(articleid: CnkiArticleIdModel):
    return_info = ReturnInfo()
    cjip = CnkiArticleId.objects(ids=articleid.ids)
    if cjip:  # mongoengine.queryset.queryset.QuerySet
        cjip.update(
            pykm=articleid.pykm, years=articleid.years,
            nums=articleid.nums, articlecount=articleid.articlecount,
            html=articleid.html, update_time=datetime.datetime.now())
        # jwpp.reload()
        return_info.status = SUCCESS
        return_info.data = {"boos": [str(j.id) for j in cjip]}
        return return_info.todict()
    else:
        cjip = CnkiArticleId(ids=articleid.ids, pykm=articleid.pykm,
                             years=articleid.years, nums=articleid.nums,
                             articlecount=articleid.articlecount,
                             html=articleid.html,
                             update_time=datetime.datetime.now(),
                             create_time=datetime.datetime.now()
                             )
        cjip.save()
        return_info.status = SUCCESS
        return_info.data = {"boos": str(cjip.id)}
        return return_info.todict()


@router.post("/insert/pdfvpnip")
async def create_note(pdfip: PdfIpModel):
    return_info = ReturnInfo()
    cjip = PdfIp.objects(ip=pdfip.ip)
    if cjip:  # mongoengine.queryset.queryset.QuerySet
        cjip.update(
            types=pdfip.types, canusecount=pdfip.canusecount, school=pdfip.school,
            status=pdfip.status, update_time=datetime.datetime.now())
        # jwpp.reload()
        return_info.status = SUCCESS
        return_info.data = {"boos": [str(j.id) for j in cjip]}
        return return_info.todict()
    else:
        cjip = PdfIp(ip=pdfip.ip, types=pdfip.types, status=pdfip.status,
                     canusecount=pdfip.canusecount, usedcount=pdfip.usedcount,
                     usecountTime=pdfip.usecountTime, num=pdfip.num,
                     uselisttime=pdfip.uselisttime, school=pdfip.school,
                     update_time=datetime.datetime.now(),
                     create_time=datetime.datetime.now()
                     )
        cjip.save()
        return_info.status = SUCCESS
        return_info.data = {"boos": str(cjip.id)}
        return return_info.todict()


@router.post("/get/pdfvpnip/{types_id}")
async def create_note(types_id: int):
    for i in range(20):
        if Globol.getvpn == 1:
            Globol.getvpn = 0
            break
        else:
            time.sleep(0.5)
    return_info = ReturnInfo()
    if types_id == 0:
        cjip = PdfIp.objects(status=1).where("this.canusecount>this.usedcount").order_by('usedcount')
    else:
        cjip = PdfIp.objects(status=1, types=types_id).where("this.canusecount>this.usedcount").order_by('usedcount')
    if cjip:  # mongoengine.queryset.queryset.QuerySet
        dictsip = cjip.first()
        list_usecount = dictsip.usecountTime
        newtime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
        list_usecount.append(newtime)
        usedcount = dictsip.usedcount
        usedcount = usedcount + 1
        dictsip.update(usecountTime=list_usecount, usedcount=usedcount, update_time=datetime.datetime.now())
        return_info.status = SUCCESS
        return_info.data = {"ip": dictsip.ip, "time": newtime}
        Globol.getvpn = 1
        return return_info.todict()
    else:
        return_info.status = FAILED
        return_info.msg = "数据库中没有对应的ip"
        Globol.getvpn = 1
        return return_info.todict()


@router.post("/update/pdfvpnip")
async def create_note(update: UpdatePdfIpModel):
    for i in range(20):
        if Globol.updatevip == 1:
            Globol.updatevip = 0
            break
        else:
            time.sleep(0.5)
    return_info = ReturnInfo()
    cjip = PdfIp.objects(ip=update.ip)
    if cjip:  # mongoengine.queryset.queryset.QuerySet
        dictsip = cjip.first()
        list_usecount = dictsip.usecountTime
        usedcount = dictsip.usedcount
        try:
            list_usecount.remove(update.time)
            usedcount = usedcount - 1
        except:
            return_info.msg = "不存在 移除失败,可能是超时被移除"
        list_time = dictsip.uselisttime
        list_time.extend(update.timelist)
        dictsip.update(usecountTime=list_usecount,
                       uselisttime=list_time,
                       usedcount=usedcount,
                       update_time=datetime.datetime.now())
        return_info.status = SUCCESS
        return_info.data = {"ip": dictsip.ip}
        Globol.updatevip = 1
        return return_info.todict()
    else:
        return_info.status = FAILED
        return_info.msg = "数据库中没有对应的ip"
        Globol.updatevip = 1
        return return_info.todict()


@router.get("/update/pdfvpnovertime")
async def create_note():
    return_info = ReturnInfo()
    cjip = PdfIp.objects()
    if cjip:  # mongoengine.queryset.queryset.QuerySet
        listsip = []
        for oneip in cjip:
            liststime = oneip.usecountTime
            count = oneip.usedcount
            lists2 = []
            for time in liststime:
                nowtime = datetime.datetime.now()
                oldtime = datetime.datetime.strptime(time, "%Y-%m-%d %H:%M:%S.%f")
                if (nowtime - oldtime).seconds > 60 * 10:
                    lists2.append(time)
            for time in lists2:
                liststime.remove(time)
                count = count - 1
            if oneip.usedcount > count:
                listsip.append(oneip.ip)
            oneip.update(usecountTime=liststime, usedcount=count, update_time=datetime.datetime.now())
        return_info.status = SUCCESS
        return_info.data = {"ip": listsip}
        Globol.updatevip = 1
        return return_info.todict()
    else:
        return_info.status = FAILED
        return_info.msg = "数据库中没有对应的ip"
        Globol.updatevip = 1
        return return_info.todict()


@router.post("/insert/cnkibsref")
async def create_note(update: CnkiBsRefModel):
    return_info = ReturnInfo()
    cjip = CnkiBsRef(rawid=update.rawid,
                     update_time=datetime.datetime.now(),
                     create_time=datetime.datetime.now()
                     )
    cjip.save()
    return_info.status = SUCCESS
    return_info.msg = ""
    return return_info.todict()
